package com.leyou.search.test;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.leyou.common.bean.Result;
import com.leyou.common.bean.ResultCode;
import com.leyou.item.inter.api.IBrandService;
import com.leyou.item.inter.api.ICategoryService;
import com.leyou.item.inter.api.IGoodsService;
import com.leyou.item.inter.api.ISpecGroupParamService;
import com.leyou.item.inter.dto.SpecSelectDTO;
import com.leyou.item.inter.pojo.*;
import com.leyou.search.entity.Goods;
import com.leyou.search.repository.GoodsRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * @author zqq
 * @ClassName ExportEearchService
 * @Description
 * @date 2020/3/7-18:56
 */
@Service
@Slf4j
public class ExportSearchService {

    @Autowired
    private ICategoryService iCategoryService;

    @Autowired
    private IBrandService iBrandService;

    @Autowired
    private IGoodsService iGoodsService;

    @Autowired
    private ISpecGroupParamService iSpecGroupParamService;

    @Autowired
    private GoodsRepository goodsRepository;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    public Goods buildGoods(Spu spu) throws IOException {
        // 创建goods对象
        Goods goods = new Goods();

        // 查询品牌
        Result<Brand> brand = this.iBrandService.queryBrandById(spu.getBrandId());

        // 查询分类名称
        Result<List<String>> names = this.iCategoryService.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));

        // 查询spu下的所有sku
        Result<List<Sku>> skus = this.iGoodsService.querySkusBySpuId(spu.getId());
        List<Long> prices = new ArrayList<>();
        List<Map<String, Object>> skuMapList = new ArrayList<>();
        // 遍历skus，获取价格集合
        skus.getData().forEach(sku ->{
            prices.add(sku.getPrice());
            Map<String, Object> skuMap = new HashMap<>();
            skuMap.put("id", sku.getId());
            skuMap.put("title", sku.getTitle());
            skuMap.put("price", sku.getPrice());
            skuMap.put("image", StringUtils.isNotBlank(sku.getImages()) ? StringUtils.split(sku.getImages(), ",")[0] : "");
            skuMapList.add(skuMap);
        });

        // 查询出所有的搜索规格参数
        SpecSelectDTO entity = new SpecSelectDTO();
        entity.setCid(spu.getCid3());
        entity.setSearching(true);
        Result<List<SpecParam>> params = this.iSpecGroupParamService.queryParams(entity);
        // 查询spuDetail。获取规格参数值
        Result<SpuDetail> spuDetail = this.iGoodsService.querySpuDetailBySpuId(spu.getId());
        // 获取通用的规格参数
        Map<Long, Object> genericSpecMap = MAPPER.readValue(spuDetail.getData().getGenericSpec(), new TypeReference<Map<Long, Object>>() {
        });
        // 获取特殊的规格参数
        Map<Long, List<Object>> specialSpecMap = MAPPER.readValue(spuDetail.getData().getSpecialSpec(), new TypeReference<Map<Long, List<Object>>>() {
        });
        // 定义map接收{规格参数名，规格参数值}
        Map<String, Object> paramMap = new HashMap<>();
        if(params.getData() != null){
            params.getData().forEach(param -> {
                // 判断是否通用规格参数
                if (param.getGeneric()) {
                    // 获取通用规格参数值
                    if(genericSpecMap.get(param.getId()) != null){
                        String value = genericSpecMap.get(param.getId()).toString();
                        // 判断是否是数值类型
                        if (param.getIsNumeric()){
                            // 如果是数值的话，判断该数值落在那个区间
                            value = chooseSegment(value, param);
                        }
                        // 把参数名和值放入结果集中
                        paramMap.put(param.getName(), value);
                    }
                } else {
                    if(specialSpecMap.get(param.getId()) != null){
                        paramMap.put(param.getName(), specialSpecMap.get(param.getId()));
                    }
                }
            });
        }

        // 设置参数
        goods.setId(spu.getId());
        goods.setCid1(spu.getCid1());
        goods.setCid2(spu.getCid2());
        goods.setCid3(spu.getCid3());
        goods.setBrandId(spu.getBrandId());
        goods.setCreateTime(spu.getCreateTime());
        goods.setSubTitle(spu.getSubTitle());
        goods.setAll(spu.getTitle() + brand.getData().getName() + StringUtils.join(names.getData(), " "));
        goods.setPrice(prices);
        goods.setSkus(MAPPER.writeValueAsString(skuMapList));
        goods.setSpecs(paramMap);

        return goods;
    }

    private String chooseSegment(String value, SpecParam p) {
        double val = NumberUtils.toDouble(value);
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = NumberUtils.toDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if(segs.length == 2){
                end = NumberUtils.toDouble(segs[1]);
            }
            // 判断是否在范围内
            if(val >= begin && val < end){
                if(segs.length == 1){
                    result = segs[0] + p.getUnit() + "以上";
                }else if(begin == 0){
                    result = segs[1] + p.getUnit() + "以下";
                }else{
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    public void createIndex(Long id) throws IOException {

        Result<Spu> spu = this.iGoodsService.querySpuById(id);
        if(!spu.success() || spu.getData() == null){
            log.info(ResultCode.GOODS_NULL_FAIL.getMsg());
            return;
        }
        // 构建商品
        Goods goods = this.buildGoods(spu.getData());

        // 保存数据到索引库
        this.goodsRepository.save(goods);
    }

    public void deleteIndex(Long id) {
        this.goodsRepository.deleteById(id);
    }
}
